iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0
AI Engineering

30 天拆解 Wearable × AI:從穿戴裝置生理訊號到AI健康洞察系列 第 9

Day 09|PPG 推出的 R-R vs ECG 的 R-R:差多少?

  • 分享至 

  • xImage
  •  

今天為什麼研究這個?

Day 4 把 RMSSD 與 SDNN 的口徑釘清楚,用的是 PhysioNet nsr2db 標註好的 R-R 序列——不是 ECG 波形,而且不乾淨:3 個長 4.7 到 7.5 秒的間期其實是訊號讀不出來的空檔,混進去就把全段 RMSSD 抬高 53%。Day 8 則走通了從 PPG 波形找峰、分窗聚合出連續心率。

心率算得出來,手錶自然會拿同一串峰去算逐拍變異度,在畫面上給出「今日 HRV:48 ms」。但那串峰來自脈搏,不是心電。差多少?

差多少會決定後面能不能修。如果只是一個穩定的常數偏移,個人基準線(Day 15)吸收得掉;如果它隨活動、隨心率漂移,那建在上面的恢復建議就沒有依據。

今天做三件事:把間期清理寫出來(異常間期、漏拍、假峰、差分斷點),補上 RMSSD 與 SDNN 的單元測試,然後拿 PPG-DaLiA 的 S1、S2 兩位受試者正面比——同一個人身上同步記錄的腕式 PPG(64 Hz)與胸帶 ECG(700 Hz),兩個通道量同一顆心臟。

Concept

抓到點只是第一步;定位點、清理規則與差分斷點都會改變結果。

1. PPG 量到的是 PRV

ECG 的相鄰 R-peak 是 R-R interval;PPG 的相鄰脈搏定位點是 pulse interval,由它算出的變異度正式叫 PRV。兩者隔著會逐拍改變的脈搏傳導時間(Schäfer & Vagedes 2013):P-P(i) = R-R(i) + PTT(i) − PTT(i−1)。固定延遲會相減消失,真正傷害指標的是延遲的變動。兩台裝置是人工對齊的:受試者在開始與結束各做一次 double-tap,用加速度特徵對上起點、再用結束那次校正 drift(Reiss 2019)。殘餘的同步誤差分不出來,所以本文不解讀絕對 lag。

2. 時間誤差如何進入指標

若每拍定位誤差 e_i 是獨立白噪音、變異數 σ²,SDNN 看見一階差,平方多 2σ²;RMSSD 又差一次,變成二階差,平方多 6σ²。慢變誤差則會在相減時抵銷。另一個已知誤差是 64 Hz 的 15.625 ms 格點:Day 6 推得 RMSSD² 多 T²/2、SDNN² 多 T²/6。今天要量它實際能解釋多少。

3. 清理後仍要保留斷點

用三道判準:生理範圍、相鄰間期的相對跳變、局部中位數的離群(參數見 Hands-on)。漏拍像接近兩倍的長間期;假峰像兩個加起來接近一拍的短間期。但標籤只描述形態,不能取代心律診斷。

剔除後不能把剩下的值接起來再 diff:缺口兩端不是相鄰兩拍。RMSSD 只算 valid[i] and valid[i+1] 的差分,分母也跟著減少。Task Force 1996 還要求報告剔除的數量與時長;同一個 RMSSD,排除 2% 和 40% 不是同一種證據。

4. 比較口徑

ECG rpeaks 也不是無誤真值:它是自動偵測器的輸出再經人工檢視修正,刪掉假峰、補回漏峰(Reiss 2019)。本文同時看逐拍誤差、RMSSD/SDNN 誤差、活動別差異與剔除率;只給一個整體 bias 會把互相抵銷與 coverage 藏起來。

Hands-on

每 120 秒算一窗、不重疊,跨活動交界的窗丟掉,共留下 117 窗。PPG 找峰時再切成 8 秒子視窗、位移 4 秒,避免長窗的全域 prominence 被少數大振幅主導;重疊窗找到的同一個峰在 31 ms 內合併。

三道判準各自算一遍再取交集,不是一道套過一道:30–220 bpm 的生理範圍、相對前一拍跳變不超過 20%(比的是前一個原始值)、21 拍局部窗內不超過 3 IQR。接著用鄰近間期辨識「接近兩倍」的漏拍與「兩個短間期加起來接近一拍」的假峰;假峰成對,會連通過三道判準的那一半一起剔掉。不內插,只保留原值、有效遮罩與原因標籤。RMSSD 的差分只有兩端都有效才算:

pair_ok = valid[:-1] & valid[1:]
diffs = np.diff(rr_ms)[pair_ok]
rmssd = np.sqrt(np.mean(diffs**2))

指標不需要配對,兩側各自用自己的間期算;但要看逐拍差就得先把拍對起來。先在 −100 ~ +600 ms 這個不對稱區間粗配、量出該窗的中位延遲(對稱容差會整段配到前一拍去,Day 3 的教訓),扣掉之後再以 200 ms 容差一對一細配。即使如此,每窗也只有約 66% 的 ECG 拍配得到 PPG 峰——散點圖上的 7,785 對就是這樣篩出來的。

先在真值已知的合成序列注入漏拍、假峰與三段訊號空檔,再跑真實雙通道比較;最後逐項替換視窗長度、清理門檻、偵測窗與定位點。完整表格與圖說在 days/day09/results.md

https://ithelp.ithome.com.tw/upload/images/20260922/20184206aVsDIDybTD.png
合成序列的清理與斷點

https://ithelp.ithome.com.tw/upload/images/20260922/201842068pNZgLrEsH.png
PPG pulse interval 與 ECG R-R

https://ithelp.ithome.com.tw/upload/images/20260922/20184206umwsKHuWM5.png
各活動的 RMSSD 與 SDNN 水準:ECG vs PPG

結果與意外

先看兩個層次。逐拍間期上,PPG 與 ECG 幾乎沒有系統性偏差:7,785 對的 bias 只有 −9.0 ms,但 95% 一致性界限寬達 −220.7 ~ +202.7 ms。到了指標層就一面倒:

指標(視窗中位數) ECG PPG 比值
平均間期 799 ms 807 ms 1.01×
RMSSD(不清理) 39.1 ms 344 ms 8.80×
RMSSD(清理後) 37.0 ms 70.0 ms 1.89×
SDNN(清理後) 64.1 ms 139 ms 2.16×

平均間期幾乎完全對得上,變異度卻差了快一倍。「差多少」的答案不是 +33.7 ms 這個毫秒數,而是這個比值。

原本以為 實際發現
漏拍與假峰清掉後,RMSSD 應該能回到真值附近 合成序列成立:三種情境的 gap-aware RMSSD 都在真值 ±1.5% 內。訊號空檔跨斷點相減會高估 46.0%,不跨斷點只差 +0.58%。
逐拍間期差不多,算出來的指標就差不多 不會。逐拍 bias 只有 −9.0 ms,RMSSD 卻有 96% 的視窗偏高。誤差相加會抵銷,取平方只會累加。
PPG 與 ECG 也許只差一個可被 baseline 吸收的固定 bias 不是。清理後 RMSSD bias 從 sitting 的 +12.4 ms 到 table soccer 的 +75.4 ms,方向雖同為偏高,幅度隨活動改變。
20% jump threshold 是一個合理的清理預設 它是最敏感的旋鈕,也是唯一真正在動的那道閘:PPG 的剔除有 45.2% 是它擋的,生理範圍只擋掉 0.68%。改 10% 時 bias +8.8 ms、排除 68.1%;改 30% 時 +67.4 ms、排除 43.1%。
定位誤差大致可以當成白噪音 不行。逐窗的時間誤差自相關 ρ₁ 中位數 0.17、ρ₂ 0.08,既不是白噪音的 0,也不是慢變的 1。
64 Hz 格點會是主要誤差 量化下界只解釋清理後 RMSSD 差的 4.9%、SDNN 的 0.4%。更大的來源是峰定位、漏拍、假峰與活動雜訊。
主峰與波谷的抖動差不多,換定位點影響有限 這兩位受試者上,波谷把 RMSSD MAE 從 33.9 降到 25.9 ms、排除率從 54.3% 降到 45.9%;是敏感度結果,不足以推廣。

清理的代價要和誤差一起報

清理確實把 raw RMSSD bias 從 +346.0 ms 降到 +33.7 ms,代價是 PPG 間期平均排除 54.3%;ECG 只排除 1.24%。

更要看的是清理後還剩下什麼。我設的「每側至少 30 個間期」擋的是清理的數量,而 RMSSD 的分母是兩端都有效的相鄰差分:清理後 PPG 每窗的有效差分中位數只剩 38 個、最少 3 個,117 窗裡有 44 窗不到 30 個(ECG 中位數 146、最少 84)。薄的窗偏差還更大:不到 30 個的窗 bias +47.9 ms,30 以上的 +25.2 ms。

活動別的排序因此和 coverage 綁在一起——table soccer 那 3 個窗的有效差分只有 3、7、12 個。「不同活動差很多」這個方向站得住,但每個活動的數值不能單獨引用。

誤差是什麼形狀的

Concept 第 2 節留了一題:時間誤差是白噪音還是慢變?都不是,ρ₁ 中位數 0.17。把實測的 σ 與 ρ 代進二階差公式預測 RMSSD 會被墊高多少,預測比實測高了 145 ms——公式是代數恆等式,對不上的是前提:它假設兩邊的拍一對一、只差一個時間誤差,而真實資料裡還有漏拍、假峰與錯配。時間誤差模型解釋得了一部分,解釋不了偵測本身出的錯。

https://ithelp.ithome.com.tw/upload/images/20260922/20184206fku3ud7OzI.png
時間誤差的結構:sd、自相關與模型殘差

Limitations

  • 只有 S1、S2;stairs 與 table soccer 各只有 3 個可用窗,活動排序不能推廣到人群。
  • 120 秒窗原本約 150 拍,清理後每窗剩下的有效差分中位數只剩 38 個、最少 3 個,薄的窗算出來的 RMSSD 本身就不穩;逐拍那層也只涵蓋配得上的 66%,而配不上的多半正是偵測最差的片段,所以 −9.0 ms 是樂觀估計。
  • ECG rpeaks 是偵測後人工修正的參考,不是無誤真值;兩台裝置又靠開始與結束的 double-tap 人工同步,所以 lag 的絕對值不能當 PTT。
  • 20% jump rule 會把真實的逐拍高頻變異一起排除,而 PPG 被剔掉的間期有 45.2% 是它擋的。平均剔除 54.3%,動作活動排得更多,留下的是非隨機子集。
  • 漏拍/假峰標籤只描述形態,不是心律診斷;單看間期無法區分演算法錯誤、早發拍或竇性停搏。
  • 峰偵測仍是簡單的 band-pass、prominence 與貪婪併峰。本文量到的是這條最小管線,不是 PPG 作為感測原理的上限。

這對 AI Engineering 的意義

一個 rmssd_ms 不足以交給模型。至少還要一起帶:來源是 ECG HRV 還是 PPG PRV、視窗長度、定位點、清理參數、有效間期與有效差分數、剔除率、活動情境,以及是否跨斷點。否則同一個人、同一段時間,同名欄位就能差到接近兩倍,而 LLM 不會因為數字變兩倍就改口,它只會照著解釋。

更重要的是,品質閘門不是把不確定性消掉,而是改變資料分布。門檻收緊後 MAE 下降,不代表感測器突然更準;也可能只是最難的 68% 被丟掉。這些 deterministic 計算與 coverage 應由 pipeline 完成並留下 provenance。LLM 可以解釋「今天資料不足,不能和 baseline 比」,不該替缺掉的間期補一個看似合理的 HRV。


上一篇
Day 08|實作:從 PPG 波形萃取心率
下一篇
Day 10|故意把訊號弄壞:Artifact 注入實驗
系列文
30 天拆解 Wearable × AI:從穿戴裝置生理訊號到AI健康洞察10
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言